﻿using System;
using UnityEngine;
using UnityEngine.UI;

// 输入窗口
public class InputBox: MonoBehaviour {
    // 回调
    public interface Callback {
        void OnInputBoxOK(int intValue);        // 用户单击"确定"按钮事件（返回整数值）
        void OnInputBoxOK(string stringValue);  // 用户单击"确定"按钮事件（返回字符串）
        void OnInputBoxCancel();                // 用户单击"取消"按钮事件
    }

    private static Callback sCallback;      // 回调
    private static int sDisplayValue;       // 显示的值
    private static GameObject sGameObject;  // 游戏物体
    private static bool sGetStringValue;    // 要获取字符串值则为 true，要获取整数值则为 false
    private static InputField sInputField;  // 编辑框
    private static int sMinValue;           // 允许输入的最小值
    private static int sMaxValue;           // 允许输入的最大值
    private static Text sTipText;           // 提示标签

    /**
     * 唤醒。
     */
    private void Awake() {
        // 初始化成员
        sDisplayValue = 0;
        sGameObject = gameObject;
        sGetStringValue = true;
        sInputField = gameObject.GetComponentInChildren<InputField>();
        sMinValue = -1;
        sMaxValue = 0;
        sTipText = sGameObject.GetComponentInChildren<Text>();
        GameObject.FindGameObjectWithTag(Const.TAG_BUTTON_OK).GetComponent<Button>().onClick.AddListener(OnOK);
        GameObject.FindGameObjectWithTag(Const.TAG_BUTTON_CANCEL).GetComponent<Button>().onClick.AddListener(OnCancel);

        // 设置遮罩尺寸为屏幕尺寸
        gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(Screen.width, Screen.height);

        // 隐藏自身
        gameObject.SetActive(false);
    }

    /**
     * "取消"按钮的单击响应方法。
     */
    private void OnCancel() {
        // 隐藏自身
        gameObject.SetActive(false);

        // 调用回调
        sCallback.OnInputBoxCancel();
    }

    /**
     * "确定"按钮的单击响应方法。
     */
    private void OnOK() {
        int intValue = 0;

        // 如果要获取字符串，则直接调用回调
        if (sGetStringValue) {
            sCallback.OnInputBoxOK(sInputField.text);
            return;
        }

        // 如果用户没有输入，则将显示值作为输入值
        if (sInputField.text == "") {
            intValue = sDisplayValue;
        } else {
            // 检查输入值
            try {
                intValue = int.Parse(sInputField.text);
                if (intValue >= sMinValue && intValue <= sMaxValue) {
                    // 隐藏自身
                    gameObject.SetActive(false);

                    // 调用回调
                    sCallback.OnInputBoxOK(intValue);
                    return;
                }
            } catch (Exception) {
            }
        }

        // 显示错误提示
        MessageBox.Show("输入的数值超出允许范围，请重新输入。", () => sInputField.ActivateInputField());
    }

    /**
     * 显示（获取整数值）。
     * @param callback      回调
     * @param tipText       提示文字
     * @param displayValue  编辑框上显示的默认值
     * @param maxValue      允许输入的最大值
     * @param minValue      允许输入的最小值
     */
    public static void Show(Callback callback, string tipText, int displayValue, int maxValue, int minValue) {
        // 设置成员
        sCallback = callback;
        sDisplayValue = displayValue;
        sGetStringValue = false;
        sMaxValue = maxValue;
        sMinValue = minValue;

        sTipText.text = tipText;
        sInputField.text = Convert.ToString(displayValue);

        // 显示
        sGameObject.SetActive(true);

        // 焦点切换到编辑框
        sInputField.ActivateInputField();
    }

    /**
     * 显示（获取字符串值）。
     * @param callback      回调
     * @param tipText       提示文字
     * @param displayValue  编辑框上显示的默认值
     */
    public static void Show(Callback callback, string tipText, string displayValue) {
        // 设置成员
        sCallback = callback;
        sTipText.text = tipText;
        sInputField.text = displayValue;

        // 显示
        sGameObject.SetActive(true);

        // 焦点切换到编辑框
        sInputField.ActivateInputField();
    }

    /**
     * 更新。
     */
    private void Update() {
        if (Input.GetKeyDown(KeyCode.Return)) {
            // 如果用户按下回车键，则相当于单击"确定"按钮
            this.OnOK();
        } else if (Input.GetKeyDown(KeyCode.Escape)) {
            // 如果用户按下 ESC 键，则相当于单击"取消"按钮
            this.OnCancel();
        }
    }
}
